import pandas as pd
import importlib
import numpy as np
import datetime 
import influxdb
import pymssql
import cx_Oracle as oracle
import warnings
from joblib import Parallel, delayed,parallel_backend
from tqdm import tqdm 
from Config.myConfig import *
from Config.myConstant import *
from DataPrepare.dailyFactorsWithInfluxdb.factorBase import factorBase
from Utility.InfluxdbUtility import InfluxdbUtility
import os
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'

########################################################################
class dailyDataPrepared(object):
    """description of class"""

    #----------------------------------------------------------------------
    def getDailyFactorsFromOracle(self,code,startDate,endDate):
        code=str(code)
        startDate=str(startDate)
        endDate=str(endDate)
        database=INFLUXDBDAILYDATABASE
        measurement=str(code)
        tag={}
        myfactor=factorBase()
        mydata=pd.DataFrame()
        factorList=DAILYFACTORSNEEDTOUPDATEWITHINFLUXDB
        for factor in factorList:
            mymodule = importlib.import_module(factor['module'])
            myclass=getattr(mymodule, factor['class'])
            myinstance=myclass()
            factorData=myinstance.getDataFromOracleByCode(code,startDate,endDate)
            if factorData.shape[0]>0:
                if mydata.shape[0]==0:
                    mydata=factorData
                else:
                    columns=list(set(factorData.columns).difference(set(mydata.columns)))
                    mydata=pd.merge(mydata,factorData[columns],how='left',left_index=True,right_index=True)
        return mydata
    
    #----------------------------------------------------------------------
    def saveDailyFactorsToInfluxdb(self,IPOList,startDate,endDate):
        startDate=str(startDate)
        endDate=str(endDate)
        for ipo in IPOList:
            code=ipo[0]
            name=ipo[1]
            listDate=ipo[4]
            if listDate>startDate:
                startDate=listDate
            delistDate=ipo[5]
            if delistDate!=None:
                if delistDate<endDate:
                    endDate=delistDate
            data=self.getDailyFactorsFromOracle(code,startDate,endDate)
            if data.shape[0]>0:
                data['name']=name
                data['listDate']=listDate
                data['delistDate']=delistDate
                data=data.drop(['code'],axis=1)
                InfluxdbUtility.saveDataFrameDataToInfluxdb(data,INFLUXDBDAILYDATABASE,'marketData',{'code':code})
                logger.info(f'data of {code} from {startDate} to {endDate} has been stored!')
            pass
        pass
    #----------------------------------------------------------------------
    def saveDailyFactorsByCodeToInfluxdb(self,ipo,startDate,endDate):
        startDate=str(startDate)
        endDate=str(endDate)
        code=ipo[0]
        name=ipo[1]
        listDate=ipo[4]
        if listDate>startDate:
            startDate=listDate
        delistDate=ipo[5]
        if delistDate!=None:
            if delistDate<endDate:
                endDate=delistDate
        data=self.getDailyFactorsFromOracle(code,startDate,endDate)
        if data.shape[0]>0:
            data['name']=name
            data['listDate']=listDate
            data['delistDate']=delistDate
            data=data.drop(['code'],axis=1)
            InfluxdbUtility.saveDataFrameDataToInfluxdb(data,INFLUXDBDAILYDATABASE,'marketData',{'code':code})
            logger.info(f'data of {code} from {startDate} to {endDate} has been stored!')
    #----------------------------------------------------------------------
    def updateDailyData(self,startDate,endDate,groupnum=MYGROUPS,myjobs=MYJOBS):
        ipoData=self.__getAllStockIPOInfoFromRDF()
        ipoData=ipoData[ipoData['listDate'].isna()==False]
        #ipoData=ipoData[ipoData['code'].isin(['000001.SZ','000066.SZ'])]
        codeList=list(ipoData.values)
        warnings.filterwarnings('ignore')
        Parallel(n_jobs=MYJOBS,verbose=0)(delayed(self.saveDailyFactorsByCodeToInfluxdb)(ipo,startDate,endDate) for ipo in codeList)
        pass
    #----------------------------------------------------------------------
    def __getAllStockIPOInfoFromRDF(self):
        oracleConnectString=OracleServer['default']
        myConnection=oracle.connect(oracleConnectString)
        myCursor=myConnection.cursor()
        oracleStr="select s_info_windcode,S_INFO_NAME,S_INFO_EXCHMARKET,S_INFO_LISTBOARD,S_INFO_LISTDATE,S_INFO_DELISTDATE from wind_filesync.AShareDescription order by S_INFO_LISTDATE"
        myCursor.execute(oracleStr)
        mydata=pd.DataFrame(myCursor.fetchall(),columns=['code','name','exchange','board','listDate','delistDate'])
        return mydata
        pass
########################################################################